home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Adobe Graphics & Publishing SDK 1996 December
/
Adobe Graphics & Publishing SDK 1996 December.iso
/
mac
/
After Effects 3.1 SDK Mac
/
Examples
/
I⁄O Samples
/
Filmstrip FXIF
/
FILM_Write.c
< prev
next >
Wrap
Text File
|
1996-06-04
|
9KB
|
406 lines
/**
FILM_Write.c
Part of the Adobe After Effects 3.1 SDK
Copyright (c)1993-96, Adobe Systems Inc, All Rights Reserved.
Revision History
1.0, created by dmw
**/
#include "PIFormatT.h"
#include "Film.h"
#include <string.h>
//╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤
// Convert a frame count into a timecode
#define DropFramesPerTenMin 17982
#define DropFramesPerMin 1798
enum {
ffFrameCount = 1, // count in frames FFFFF
ffNonDrop24 = 24, // 24fps HH:MM:SS:FF
ffNonDrop25 = 25, // 25fps HH:MM:SS:FF
ffNonDrop30 = 30, // 30fps, non-drop HH:MM:SS:FF
ffNonDrop100 = 100, // 100fps HH:MM:SS:FFF
ffNonDrop600 = 600, // 600fps HH:MM:SS:FFF
ffDropFrame = 29, // 30fps, drop-frame HH;MM;SS;FF
ffFeetFrame16 = 16, // Feet.Frames (35mm) ffff.FF
ffFeetFrame40 = 40, // Feet.Frames (16mm) ffff.FF
ffType = 0x03FF, // mask for types
ffDelta = 0x4000, // delta symbol in front of time
ffTensHours = 0x3000, // show tens of hours
ffTensFlag = 0x2000, // test bit for tens of hours
ffHours = 0x1000, // show hours
ffOffset = 0x0800 // +SS:FF or -SS:FF
};
//╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤
// append two pascal strings
static void Append (StringPtr str1, StringPtr str2)
{
BlockMove(str2+1,str1+1+str1[0],str2[0]);
str1[0] += str2[0];
}
//╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤
// Do a numeric conversion to H:MM:SS:FFF
static void LocalConvert (long time, short fps, short flags, char sep, StringPtr number)
{
short i = 1, hours, mins, secs, frames;
if (time < 0) {
number[i++] = '-';
time = -time;
}
frames = time % fps;
secs = (time / fps) % 60;
mins = (time / (fps * 60)) % 60;
hours = (time / (fps * 60 * 60)) % 60;
if (!(flags & ffOffset)) {
if (flags & ffTensFlag) {
number[i++] = '0' + ((hours / 10) % 10);
}
if (flags & ffHours) {
number[i++] = '0' + (hours % 10);
number[i++] = sep;
}
number[i++] = '0' + ((mins / 10) % 10);
number[i++] = '0' + (mins % 10);
number[i++] = sep;
}
number[i++] = '0' + ((secs / 10) % 10);
number[i++] = '0' + (secs % 10);
number[i++] = sep;
if (fps <= 100) {
number[i++] = '0' + ((frames / 10) % 10);
number[i++] = '0' + (frames % 10);
}
else {
number[i++] = '0' + ((frames / 100) % 10);
number[i++] = '0' + ((frames / 10) % 10);
number[i++] = '0' + (frames % 10);
}
number[0] = i-1;
}
static void TimecodeToStr (long frames, short format, StringPtr str)
{
Str63 temp;
short fps, remain;
long offset;
switch (format & ffType) {
case ffFeetFrame16:
case ffFeetFrame40:
str[0] = 0;
switch (format & ffType) {
case ffFeetFrame16: fps = 16; break;
case ffFeetFrame40: fps = 40; break;
}
if (frames < 0) {
Append(str, (StringPtr)"\p-");
frames = -frames;
}
NumToString(frames / fps, temp);
Append(str, temp);
NumToString(remain = frames % fps, temp);
Append(str, (StringPtr)"\p+");
if (remain < 10) Append(str, (StringPtr)"\p0");
Append(str, temp);
break;
case ffNonDrop24:
case ffNonDrop25:
case ffNonDrop30:
case ffNonDrop100:
case ffNonDrop600:
switch (format & ffType) {
case ffNonDrop24: fps = 24; break;
case ffNonDrop25: fps = 25; break;
case ffNonDrop30: fps = 30; break;
case ffNonDrop100: fps = 100; break;
case ffNonDrop600: fps = 600; break;
}
LocalConvert(frames, fps, format, ':', str);
break;
case ffDropFrame:
offset = (frames / DropFramesPerTenMin) * 18; // 18 frames per 10 minutes
remain = frames % DropFramesPerTenMin; // how much left over?
if (remain >= 1800) { // first minute is special
offset += 2;
remain -= 1800;
}
else remain = 0;
offset += (remain / DropFramesPerMin) * 2; // 2 frames per minute
LocalConvert(frames + offset, 30, format, ';', str);
break;
case ffFrameCount:
str[0] = 0;
NumToString(frames, temp);
Append(str, temp);
break;
default:
Append(str, (StringPtr)"\p----");
break;
}
}
static OSErr DrawLeading (FormatRecordTPtr fpt)
{
OSErr err = 0;
long rowbytes;
GWorldPtr destworld;
GWorldPtr oldworld;
GDHandle olddev;
Ptr base;
SInt8 mode;
myRevertInfo** ri;
RGBColor thecolor;
Rect padrect;
Str31 str;
Str27 temp;
long i;
char *src;
char *dst = fpt->data;
long *dst_l;
long j;
char a;
ri = (myRevertInfo**)fpt->revertInfo;
destworld = DH(ri)->number_wld;
padrect.top = padrect.left = 0;
padrect.right = fpt->imageSize.h;
padrect.bottom = FILM_LEAD;
mode = true32b;
SwapMMUMode(&mode);
if (LockPixels(destworld->portPixMap)) {
base = GetPixBaseAddr(destworld->portPixMap);
rowbytes = (*destworld->portPixMap)->rowBytes & 0x3FFF;
GetGWorld(&oldworld,&olddev);
SetGWorld(destworld,nil);
// TextFont(geneva);
TextSize(9);
thecolor.red = thecolor.green = thecolor.blue = 0xBFFF;
RGBForeColor(&thecolor);
PaintRect(&padrect);
thecolor.red = 0xFFFF;
thecolor.green = 0xFFFF;
thecolor.blue = 0;
RGBForeColor(&thecolor);
MoveTo(padrect.left,padrect.top);
Line(0,0);
thecolor.red = thecolor.green = thecolor.blue = 0;
RGBForeColor(&thecolor);
TimecodeToStr(DH(ri)->film_rec.numFrames, DH(ri)->film_rec.framesPerSec, str);
MoveTo(padrect.left+4,padrect.bottom-5);
DrawString(str);
NumToString(DH(ri)->film_rec.numFrames,temp);
for (i=0; i<5-temp[0]; i++) str[i+1] = '0';
str[0] = 5-temp[0];
Append(str,temp);
MoveTo(padrect.right-4-StringWidth(str),padrect.bottom-5);
DrawString(str);
// now destworld has the frame #/timecode in it --> copy it into fpt->data
src = base;
for (i=0; i<FILM_LEAD; i++) {
BlockMove(src, dst, sizeof(long) * padrect.right);
dst_l = (long*)dst;
for (j=0; j<padrect.right; j++) {
a = *(char*)dst_l;
*dst_l = (*dst_l) << 8;
((char*)dst_l)[3] = a;
dst_l++;
}
dst += sizeof(long) * padrect.right;
src += rowbytes;
}
UnlockPixels(destworld->portPixMap);
}
SetGWorld(oldworld,olddev);
SwapMMUMode(&mode);
return err;
}
void WritePrepare (Ptr Stuff, long *data, short *result)
{
FormatRecordPtr fp = (FormatRecordPtr)Stuff;
fp -> maxData /= 2;
*result = 0;
}
void WriteStart (Ptr Stuff, long *data, short *result)
{
OSErr err = 0;
myRevertInfo **ri;
FormatRecordTPtr fpt = (FormatRecordTPtr)(Stuff - sizeof(TimeExtension));
TimeInfoHandle ti;
Handle dataH;
ri = (myRevertInfo**)fpt->revertInfo;
ti = fpt->time_ext.time_info;
if (ri) {
long rowsat;
rowsat = fpt->maxData / (4L * (long)fpt->imageSize.h);
if (rowsat < FILM_LEAD) rowsat = FILM_LEAD;
else if (rowsat > fpt->imageSize.v) rowsat = fpt->imageSize.v;
DH(ri)->rowsat = rowsat;
DH(ri)->film_rec.framesPerSec = (DH(ti)->write_fixed_fps) >> 16;
DH(ri)->dataH = NULL;
dataH = NewHandle(rowsat * (long)fpt->imageSize.h * 4L);
if (dataH) {
HLock(dataH);
DH(ri)->dataH = dataH;
fpt->data = DH(dataH);
fpt->theRect.left = 0;
fpt->theRect.right = fpt->imageSize.h;
fpt->theRect.top = 0;
fpt->theRect.bottom = rowsat;
fpt->loPlane = 0;
fpt->hiPlane = 3;
fpt->colBytes = 4;
fpt->rowBytes = 4 * (long)fpt->imageSize.h;
fpt->planeBytes = 1;
} else {
err = memFullErr;
}
} else {
err = formatBadParameters;
}
*result = err;
}
void WriteContinue (Ptr Stuff, long *data, short *result)
{
OSErr err = 0;
myRevertInfo **ri;
FormatRecordTPtr fpt = (FormatRecordTPtr)(Stuff - sizeof(TimeExtension));
TimeInfoHandle ti;
long bytes_written;
long rows;
Boolean done = FALSE;
ri = (myRevertInfo**)fpt->revertInfo;
ti = fpt->time_ext.time_info;
if (fpt->advanceState == NULL) {
err = errPlugInHostInsufficient;
}
if (!err) {
err = SetFPos(fpt->dataFork, fsFromLEOF, 0);
}
if (!err) {
if (ri && fpt->data) {
do {
rows = fpt->theRect.bottom - fpt->theRect.top;
bytes_written = fpt->imageSize.h * rows * 4L;
err = FSWrite(fpt->dataFork, &bytes_written, fpt->data);
if (err) break;
fpt->theRect.top = fpt->theRect.bottom;
fpt->theRect.bottom = fpt->theRect.top + DH(ri)->rowsat;
if (fpt->theRect.bottom > fpt->imageSize.v)
fpt->theRect.bottom = fpt->imageSize.v;
if (fpt->theRect.top >= fpt->imageSize.v) done = TRUE;
if (!done) fpt->advanceState();
} while (!done);
if (!err) {
bytes_written = fpt->imageSize.h * FILM_LEAD * 4;
err = DrawLeading(fpt);
if (!err) {
err = FSWrite(fpt->dataFork, &bytes_written, fpt->data);
}
}
fpt->data = NULL;
DisposeHandle(DH(ri)->dataH);
DH(ri)->dataH = NULL;
DH(ri)->film_rec.numFrames++;
} else {
err = formatBadParameters;
}
}
*result = err;
}
void WriteFinish (Ptr Stuff, long *data, short *result)
{
myRevertInfo **ri;
FormatRecordTPtr fpt = (FormatRecordTPtr)(Stuff - sizeof(TimeExtension));
TimeInfoHandle ti;
ri = (myRevertInfo**)fpt->revertInfo;
ti = fpt->time_ext.time_info;
*result = 0;
if (ri) {
DisposeHandle(DH(ri)->dataH);
DH(ri)->dataH = NULL;
fpt->data = NULL;
} else {
*result = formatBadParameters;
}
}